Application Load BalancerとAWS Lambdaでベーシック認証をかけたコンテンツを作成する #reinvent
こんにちは。サービスグループの武田です。
1週間に渡るre:Invent 2018も終わりを迎え、クラスメソッドメンバー一同も日本への帰路へとつきました。さまざまな新サービスやアップデートが発表されDevelopers.IOでもやってみたブログが多数上がっています。
さて今回は、Application Load Balancer(以下、ALB)とAWS Lambdaが連携できるようになったことを受け、Lambdaでベーシック認証をかける方法を試してみました。
やってみた
今回作成するLambda関数は次のとおりです。
'use strict'; exports.handler = async (event, context) => { const headers = event.headers || {}; // ALB Health check if (headers['user-agent'] === 'ELB-HealthChecker/2.0') { return { statusCode: 200, statusDescription: '200 OK', isBase64Encoded: false, headers: { 'Content-Type': 'text/html' } }; } // Configure authentication const authUser = process.env.AUTH_USER; const authPass = process.env.AUTH_PASS; // Construct the Basic Auth string const authString = 'Basic ' + new Buffer(authUser + ':' + authPass).toString('base64'); // Require Basic authentication if (headers.authorization !== authString) { return { statusCode: 401, statusDescription: '401 Unauthorized', body: 'Unauthorized', isBase64Encoded: false, headers: { 'WWW-Authenticate': 'Basic', 'Content-Type': 'text/html' } }; } // OK Basic authentication const response = { statusCode: 200, statusDescription: '200 OK', isBase64Encoded: false, headers: { 'Content-Type': 'text/html' } }; response.body = 'Authentication succeeded!'; return response; };
ALBからのヘルスチェックはユーザーエージェントを見て処理します(6行目)。22行目はユーザーから送信された認証情報と比較するために文字列を組み立てます。38行目以降が認証できた場合に行う処理となります。
それではマネジメントコンソールにアクセスしてやってみます。リージョンは東京です。
まずはLambdaのコンソールにアクセスし、[関数の作成]をクリックします。
名前は適当にbasic-auth
、ランタイムは今回Node.js 8.10
を選択。ロールはなんでもいいですが、今回はCloudWatchの権限がついたロールを付与しました。
関数が作成できたら、関数コードに上記のソースコードを貼り付けます。
環境変数としてAUTH_USER
とAUTH_PASS
を設定します。今回はそれぞれcm_user
とreinvent2018
を設定しました。設定できたら右上の[保存]ボタンをクリックします。
保存できました。
続いてALBを作成します。名前はbasic-auth-test
としました。ポートは80です。
AZの指定が必要ですので、適当に選んでおきます。
セキュリティグループは自分の環境からアクセスできるものを設定しましょう。今回は新規に作成しました。
ターゲットグループの指定です。ターゲットの種類として Lambda関数 が指定できますね。これを選択すると、関数を紐付けるUIに変わるので先ほど作成したbasic-auth
を指定します。またヘルスチェックも有効化しておきます。
最後に確認画面です。間違いなければ[作成]ボタンをクリックしましょう。
作成後少し待っているとステータスが healthy になるはずです。
それではALBのURLを指定してブラウザからアクセスしてみましょう。ベーシック認証のダイアログが出ました!
適当なID/PWを入力すると弾かれます。
環境変数に設定したID/PWを入力すると……。
認証が通ってコンテンツが表示されました!
さいごに
ALBのターゲットグループにLambdaが指定できるようになったことで新しい可能性が出てきたのではないかと思われます。Amazon CloudFrontとAWS Lambda@Edgeでベーシック認証をかける構成を西村が書いていました。
この構成ではLambda関数はフィルターとして機能していましたが、今回の構成ではLambda関数はエンドポイントとなります(あくまでALBのルーティング先のひとつ)。そのためとりあえず興味本位と勢いで検証しましたが、実際にどういうユースケースで役立てられるのかピンときていません。誰か教えてください。